home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is bookmark transaction code.
- *
- * The Initial Developer of the Original Code is
- * Joey Minta <jminta@gmail.com>
- *
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- function bookmarkTransactionManager() {
- this.wrappedJSObject = this;
- this.mTransactionManager = Components.classes["@mozilla.org/transactionmanager;1"]
- .createInstance(Components.interfaces.nsITransactionManager);
-
- this.mBatchCount = 0;
-
- this.classInfo = {
- getInterfaces: function (count) {
- var ifaces = [
- Components.interfaces.nsISupports,
- Components.interfaces.nsIClassInfo
- ];
- count.value = ifaces.length;
- return ifaces;
- },
-
- getHelperForLanguage: function (language) {
- return null;
- },
-
- contractID: "@mozilla.org/bookmarks/transactionManager;1",
- classDescription: "Booksmarks Transaction Manager",
- classID: Components.ID("{62d2f7fb-acd2-4876-aa2d-b607de9329ff}"),
- implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
- flags: 0
- };
-
- // Define our transactions
- function bkmkTxn() {
- this.item = null;
- this.parent = null;
- this.index = null;
- this.removedProp = null;
- };
-
- bkmkTxn.prototype = {
- BMDS: null,
-
- QueryInterface: function bkmkTxnQI(iid) {
- if (!iid.equals(Components.interfaces.nsITransaction) &&
- !iid.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
-
- return this;
- },
-
- merge : function (aTxn) {return false},
- getHelperForLanguage: function (aCount) {return null},
- getInterfaces : function (aCount) {return null},
- canCreateWrapper : function (aIID) {return "AllAccess"},
-
- RDFCU: Components.classes["@mozilla.org/rdf/container-utils;1"]
- .getService(Components.interfaces.nsIRDFContainerUtils),
-
- getParents: function getParents(aResource) {
- var parents = [];
- var arcs = this.BMDS.ArcLabelsIn(aResource);
- while (arcs && arcs.hasMoreElements()) {
- var testresource = arcs.getNext();
- if (testresource && testresource.QueryInterface) {
- testresource.QueryInterface(Components.interfaces.nsIRDFResource);
- if (this.RDFCU.IsOrdinalProperty(testresource)) {
- var source = this.BMDS.GetSource(testresource, aResource, true)
- .QueryInterface(Components.interfaces.nsIRDFResource);
- if (parents.indexOf(source) == -1) {
- //dump("CDC: found parent: "+source.Value+"\n");
- parents.push(source);
- }
- }
- }
- }
- //dump("CDC: found "+parents.length+" parents\n");
- return parents;
- },
-
- mAssertProperties: function bkmkTxnAssertProps(aProps) {
- if (!aProps) {
- return;
- }
-
- //for each (var prop in aProps) { // Mozilla bug. Bruno
- for (var i = 0; i < this.Properties.length; i++) {
- var oldValue = this.BMDS.GetTarget(this.item, this.Properties[i], true);
- // must check, if paste call after copy the oldvalue didn't remove.
- if (!oldValue) {
- var newValue = aProps[i];
- if (newValue) {
- this.BMDS.Assert(this.item,
- this.Properties[i],
- newValue, true);
- }
- } else {
- this.removedProp[i] = oldValue;
- }
- }
- //}
- },
-
- mUnassertProperties: function bkmkTxnUnassertProps(aProps) {
- if (!aProps) {
- return;
- }
- //for each (var prop in aProps) {// Mozilla bug. Bruno
- for (var i = 0; i < this.Properties.length; i++) {
- var oldValue = aProps[i];
- if (oldValue) {
- this.BMDS.Unassert(this.item, this.Properties[i], oldValue);
- }
- }
- //}
- }
- };
-
- bkmkTxn.prototype.RDFC =
- Components.classes["@mozilla.org/rdf/container;1"]
- .createInstance(Components.interfaces.nsIRDFContainer);
- var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
- .getService(Components.interfaces.nsIRDFService);
- bkmkTxn.prototype.BMDS = rdfService.GetDataSource("rdf:flock-favorites");
-
- bkmkTxn.prototype.Properties =
- [rdfService.GetResource("http://home.netscape.com/NC-rdf#Name"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#URL"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#Description"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#WebPanel"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#FeedURL"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumGenURI"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumExpiration"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#GeneratedTitle"),
- rdfService.GetResource("http://home.netscape.com/NC-rdf#BookmarkAddDate"),
- rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastModifiedDate"),
- rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastVisitDate"),
- rdfService.GetResource("http://home.netscape.com/WEB-rdf#LastCharset"),
- rdfService.GetResource("http://flock.com/rdf#flockType"),
- rdfService.GetResource("http://flock.com/rdf#isTransient"),
- rdfService.GetResource("http://flock.com/rdf#isIndexable"),
- rdfService.GetResource("http://flock.com/rdf#unseenItems"),
- rdfService.GetResource("http://flock.com/rdf#count"),
- rdfService.GetResource("http://flock.com/rdf#maxItems"),
- rdfService.GetResource("http://flock.com/rdf#capItems"),
- rdfService.GetResource("http://flock.com/rdf#hasUnseenItems"),
- rdfService.GetResource("http://flock.com/rdf#isPollable"),
- rdfService.GetResource("http://flock.com/rdf#refreshing"),
- rdfService.GetResource("http://flock.com/rdf#shared"),
- rdfService.GetResource("http://flock.com/rdf#favicon"),
- rdfService.GetResource("http://flock.com/rdf#tags"),
- rdfService.GetResource("http://flock.com/rdf#lastItemDate"),
- rdfService.GetResource("http://flock.com/rdf#lastRefresh"),
- rdfService.GetResource("http://flock.com/rdf#lastQuery"),
- rdfService.GetResource("http://flock.com/rdf#refreshInterval"),
- rdfService.GetResource("http://flock.com/rdf#datevalue"),
- rdfService.GetResource("http://flock.com/rdf#CoopType"),
- rdfService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")];
-
- function bkmkInsertTxn(aAction) {
- this.type = "insert";
- // move container declaration to here so it can be recognized if
- // undoTransaction is call after the BM manager is close and reopen.
- this.container = Components.classes["@mozilla.org/rdf/container;1"]
- .createInstance(Components.interfaces.nsIRDFContainer);
- }
-
- bkmkInsertTxn.prototype = {
- __proto__: bkmkTxn.prototype,
-
- isTransient: false,
-
- doTransaction: function bkmkInsertDoTxn() {
- this.RDFC.Init(this.BMDS, this.parent);
- // if the index is -1, we use appendElement, and then update the
- // index so that undoTransaction can still function
- if (this.index == -1) {
- this.RDFC.AppendElement(this.item);
- this.index = this.RDFC.GetCount();
- } else {
- /*XXX- broken insert code, see bug 264571
- try {
- this.RDFC.InsertElementAt(this.item, this.index, true);
- } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
- // if this failed, then we assume that we really want to append,
- // because things are out of whack until we renumber.
- this.RDFC.AppendElement(this.item);
- // and then fix up the index so undo works
- this.index = this.RDFC.GetCount();
- }
- */
- this.RDFC.InsertElementAt(this.item, this.index, true);
- }
-
- // insert back all the properties
- this.mAssertProperties(this.removedProp);
- },
-
- undoTransaction: function bkmkInsertUndoTxn() {
- // XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
- this.container.Init(this.BMDS, this.parent);
-
- // remove all properties befor we remove the element so
- // nsLocalSearchService doesn't return deleted element in Search
- this.mUnassertProperties(this.removedProp);
-
- this.container.RemoveElementAt(this.index, true);
- },
-
- redoTransaction: function bkmkInsertRedoTxn() {
- this.doTransaction();
- }
- };
-
- function bkmkRemoveTxn() {
- this.type = "remove";
- }
-
- bkmkRemoveTxn.prototype = {
- __proto__: bkmkTxn.prototype,
-
- isTransient: false,
-
- doTransaction: function bkmkRemoveDoTxn() {
- this.RDFC.Init(this.BMDS, this.parent);
-
- // remove all properties befor we remove the element so
- // nsLocalSearchService doesn't return deleted element in Search
- this.mUnassertProperties(this.removedProp);
-
- this.RDFC.RemoveElementAt(this.index, false);
- },
-
- undoTransaction: function bkmkRemoveUndoTxn() {
- this.RDFC.Init(this.BMDS, this.parent);
- this.RDFC.InsertElementAt(this.item, this.index, false);
-
- // insert back all the properties
- this.mAssertProperties(this.removedProp);
- },
-
- redoTransaction: function () {
- this.doTransaction();
- }
- }
-
- function bkmkRemoveAllTxn() {
- this.type = "removeAll";
- }
-
- bkmkRemoveAllTxn.prototype = {
- __proto__: bkmkTxn.prototype,
-
- isTransient: false,
-
- childContainer:
- Components.classes["@mozilla.org/rdf/container;1"]
- .createInstance(Components.interfaces.nsIRDFContainer),
-
- doTransaction: function bkmkRemoveDoTxn() {
- this.item.QueryInterface(Components.interfaces.nsIRDFResource);
- //dump("CDC: bkmkRemoveAllDoTxn('"+this.item.Value+"')\n");
-
- checkTopSitesRequirement = function checkTopSitesRequirement(aParents) {
- for(var i=0;i<aParents.length;i++) {
- var parent = aParents[i];
-
- if(parent.Value == "urn:flock:topsites") {
- return true;
- }
- }
-
- return false;
- };
-
- // When 'deleting' a bookmark item, we only want to REALLY delete
- // it if it has EXACTLY one parent
- if ( (this.getParents(this.item).length == 1)
- || (this.getParents(this.item).length == 2 && checkTopSitesRequirement(this.getParents(this.item)))
- ) {
- // First, recursively delete any children of this one...
- if (this.RDFCU.IsContainer(this.BMDS, this.item)) {
- this.childContainer.Init(this.BMDS, this.item);
- var children = this.childContainer.GetElements();
- this.mSubTransactions = [];
- while (children && children.hasMoreElements()) {
- var child = children.getNext();
- var txn = new bkmkRemoveAllTxn();
- txn.item = child;
- txn.parent = this.item;
- txn.index = this.childContainer.IndexOf(child);
- txn.action = this.action;
- txn.removedProp = [];
- for (var i = 0; i < this.Properties.length; i++) {
- txn.removedProp[i] = this.BMDS.GetTarget(child, this.Properties[i], true);
- }
- txn.wrappedJSObject = txn;
- this.mSubTransactions.push(txn);
- }
- for (var i = 0; i < this.mSubTransactions.length; i++) {
- this.mSubTransactions[i].doTransaction();
- }
- }
-
- // Remove all properties before we remove the element so
- // nsLocalSearchService doesn't return deleted element in Search
- this.mUnassertProperties(this.removedProp);
- }
-
- // Remove the item from its parent (this always gets done,
- // regardless of how many other parents there might be)
- //dump("CDC: bkmkRemoveAllDoTxn "+this.index+"\n");
- try {
- this.RDFC.Init(this.BMDS, this.parent);
- //If index == -1 then we don't have an index to remove
- // this can happen when bookmark is created and then removed, it might not have an index
- if(this.index > -1)
- this.RDFC.RemoveElementAt(this.index, false);
- }catch(e)
- {
- }
-
- },
-
- undoTransaction: function bkmkRemoveUndoTxn() {
- // Reinstate the arc to the main parent
- this.RDFC.Init(this.BMDS, this.parent);
- this.RDFC.InsertElementAt(this.item, this.index, false);
-
- if (this.getParents(this.item).length == 1) {
- // insert back all the properties
- this.mAssertProperties(this.removedProp);
-
- // Undo all the sub-transactions (contained bookmarks)
- if (this.mSubTransactions) {
- for (var i = this.mSubTransactions.length - 1; i >= 0; i--) {
- this.mSubTransactions[i].undoTransaction();
- this.mSubTransactions[i] = undefined;
- }
- this.mSubTransactions = undefined;
- }
- }
- },
-
- redoTransaction: function () {
- this.doTransaction();
- }
- }
-
- function bkmkImportTxn(aAction) {
- this.type = "import";
- this.action = aAction;
- }
-
- bkmkImportTxn.prototype = {
- __proto__: bkmkTxn.prototype,
-
- isTransient: false,
-
- doTransaction: function bkmkImportDoTxn() {},
-
- undoTransaction: function mkmkImportUndoTxn() {
- this.RDFC.Init(this.BMDS, this.parent);
- this.RDFC.RemoveElementAt(this.index, true);
- },
-
- redoTransaction: function bkmkImportredoTxn() {
- this.RDFC.Init(this.BMDS, this.parent);
- this.RDFC.InsertElementAt(this.item, this.index, true);
- }
- };
-
- this.BookmarkRemoveTransaction = bkmkRemoveTxn;
- this.BookmarkRemoveAllTransaction = bkmkRemoveAllTxn;
- this.BookmarkInsertTransaction = bkmkInsertTxn;
- this.BookmarkImportTransaction = bkmkImportTxn;
- }
-
- bookmarkTransactionManager.prototype.QueryInterface = function bkTxnMgrQI(aIID) {
- if (aIID.equals(Components.interfaces.nsISupports) ||
- aIID.equals(Components.interfaces.nsIBookmarkTransactionManager)) {
- return this;
- }
- if (aIID.equals(Components.interfaces.nsIClassInfo)) {
- return this.classInfo;
- }
-
- throw NS_ERROR_NO_INTERFACE;
- }
-
- bookmarkTransactionManager.prototype.createAndCommitTxn =
- function bkmkTxnMgrCandC(aType, aAction, aItem, aIndex, aParent, aPropCount, aRemovedProps) {
- //dump("CDC: createAndCommitTxn(aType='"+aType+"', aAction='"+aAction+"', aIndex="+aIndex+")\n");
- var txn;
- var nsIBookmarkTransactionManager = Components.interfaces.nsIBookmarkTransactionManager;
- switch (aType) {
- case nsIBookmarkTransactionManager.IMPORT:
- txn = new this.BookmarkImportTransaction(aAction);
- break;
- case nsIBookmarkTransactionManager.INSERT:
- txn = new this.BookmarkInsertTransaction(aAction);
- break;
- case nsIBookmarkTransactionManager.REMOVE:
- if (aAction == "move") {
- txn = new this.BookmarkRemoveTransaction(aAction);
- } else {
- txn = new this.BookmarkRemoveAllTransaction(aAction);
- }
- break;
- default:
- Components.utils.reportError("Unknown bookmark transaction type:"+aType);
- throw NS_ERROR_FAILURE;
- }
- txn.item = aItem;
- txn.parent = aParent;
- txn.index = aIndex;
- txn.removedProp = aRemovedProps;
- txn.action = aAction;
- txn.wrappedJSObject = txn;
- this.mTransactionManager.doTransaction(txn);
- //dump("CDC: end createAndCommitTxn(aType='"+aType+"', aAction='"+aAction+"', aIndex="+aIndex+")\n");
- }
-
- bookmarkTransactionManager.prototype.startBatch = function bkmkTxnMgrUndo() {
- if (this.mBatchCount == 0) {
- this.mTransactionManager.beginBatch();
- }
- this.mBatchCount++;
- }
-
- bookmarkTransactionManager.prototype.endBatch = function bkmkTxnMgrUndo() {
- this.mBatchCount--;
- if (this.mBatchCount == 0) {
- this.mTransactionManager.endBatch();
- }
- }
-
- bookmarkTransactionManager.prototype.undo = function bkmkTxnMgrUndo() {
- this.mTransactionManager.undoTransaction();
- }
-
- bookmarkTransactionManager.prototype.redo = function bkmkTxnMgrRedo() {
- this.mTransactionManager.redoTransaction();
- }
-
- bookmarkTransactionManager.prototype.canUndo = function bkmkTxnMgrCanUndo() {
- return this.mTransactionManager.numberOfUndoItems > 0;
- }
-
- bookmarkTransactionManager.prototype.canRedo = function bkmkTxnMgrCanRedo() {
- return this.mTransactionManager.numberOfRedoItems > 0;
- }
-
- bookmarkTransactionManager.prototype.__defineGetter__("transactionManager",
- function bkmkTxnMgrGetter() { return this.mTransactionManager; });
-
- /****
- **** module registration
- ****/
-
- const kFactory = {
- createInstance: function (outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return (new bookmarkTransactionManager()).QueryInterface(iid);
- }
- };
-
- var bkmkTxnMgrModule = {
- mCID: Components.ID("{8be133d0-681d-4f0b-972b-6a68e41afb62}"),
- mContractID: "@mozilla.org/bookmarks/transactionmanager;1",
-
- registerSelf: function (compMgr, fileSpec, location, type) {
- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- compMgr.registerFactoryLocation(this.mCID,
- "Bookmark Transaction Manager",
- this.mContractID,
- fileSpec,
- location,
- type);
- },
-
- getClassObject: function (compMgr, cid, iid) {
- if (!cid.equals(this.mCID))
- throw Components.results.NS_ERROR_NO_INTERFACE;
-
- if (!iid.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- return kFactory;
- },
-
- canUnload: function(compMgr) {
- return true;
- }
- };
-
- function NSGetModule(compMgr, fileSpec) {
- return bkmkTxnMgrModule;
- }
-